import { defineComponent, toRefs, ref, computed, PropType, onMounted, watch, onBeforeUnmount, nextTick, unref } from "vue";


import MainNodeProcessWrap from '@src/modules/trigger/components/ProcessNodeChart/components/MainNodeProcessWrap'
import ArrowLine from '@src/modules/trigger/components/ProcessNodeChart/components/ArrowLine'
import AddOperatorNode from '@src/modules/trigger/components/ProcessNodeChart/components/AddOperatorNode'
import NodeTriggerContent from '@src/modules/trigger/components/ProcessNodeChart/components/nodeTriggerContent.tsx'
import NodeExecuteContent from '@src/modules/trigger/components/ProcessNodeChart/components/nodeExecuteContent.tsx'
/* enum */
import { TriggerType } from '@src/modules/trigger/model/enum/index.ts'
import { NodeTypeEnum } from '@src/modules/trigger/model/enum/index.ts'
import { useCurrentInstance,useState } from '@src/modules/trigger/hooks/useVC.ts'
/* utils */
import { findComponentUpward } from '@src/util/assist';
/* type */
import type { ProcessNodeListItem } from '@src/modules/trigger/model/interface/index.ts'
import type { AllNodeType } from '@src/modules/trigger/model/enum/cell.ts'
import type { deleteMode } from '@src/modules/trigger/model/type/index.ts'
/* state */
import state from '@src/modules/trigger/view/setting/util/state.js'
/* hooks */
import { getNodeType } from '@src/modules/trigger/utils/index.ts'
import '@src/modules/trigger/components/ProcessNodeChart/style/node.scss'

export default defineComponent({
    name: TriggerType.triggerDesignNormalNode,
    props: {
        nodeData: {
            type: Object as PropType<ProcessNodeListItem>,
            default: ()=> {}
        },
        nodeIndex: {
            type: Number,
            default: 1
        }
    },
    setup(props) {
        const { nodeData } = toRefs(props)
        const [isEdit, setIsEdit] = useState(false)
        const [currentCtx, setData] = useCurrentInstance()
        const h = currentCtx?.$createElement
        const hasUpdateEmit = ref(false)
        const nodeName = ref(nodeData.value.name)
        const inputRef = ref(null)
        const boxRef = ref<HTMLDivElement | null>(null)
        const parentConditionDeleteFlag = ref(false) // 条件组删除标志
        const selectNodeClass = computed(() => {
            return state.currentSelectNode === nodeData.value.uniqueId
        })
        const validateClass = computed(() => {
            if (['code', NodeTypeEnum.START_NODE].includes(unref(currentStatusType))) {
                return true
            }
            return (nodeData.value.options && nodeData.value.options?.requiredCheck) || false
        })

        // 当前节点类型
        const currentStatusType = computed(() => {
            return getNodeType(nodeData.value)
        })

        // 第一个节点为事件触发内容
        const actionStatus = computed(() => {
            return unref(currentStatusType) === NodeTypeEnum.START_NODE
        })

        const cNodeIndex = computed(() => {
            return props.nodeIndex + 1
        })

        // 显示两个选择删除
        const showSelect = computed(() => {
            return showDeleteCurrent.value && showDeleteAll.value
        })
        const showDeleteCurrent = computed(() => {
            const parentConditionNode = findComponentUpward(currentCtx, 'ConditionOrParallelNode')
            // 当前节点必须是条件节点，且父节点是条件组节点且条件节点children长度为1 - 此时就可以删除当个条件
            parentConditionDeleteFlag.value = (nodeData.value.type === NodeTypeEnum.CONDITION_NODE && parentConditionNode && parentConditionNode.$props.nodeData.type === NodeTypeEnum.CONDITION && parentConditionNode.$props.nodeData.children.length === 1)
            // 如果当前节点父节点是条件节点，且子节点是一个条件组，则不是删除当个，而是删除一下全部
            if (nodeData.value?.parentNode?.type === NodeTypeEnum.CONDITION_NODE && nodeData.value?.children[0]?.type === NodeTypeEnum.CONDITION) {
                return false
            }
            return (nodeData.value.type !== NodeTypeEnum.CONDITION_NODE || nodeData.value.children.length === 0) || parentConditionDeleteFlag.value
        })
        const showDeleteAll = computed(() => {
            return nodeData.value.children.length > 0
        })
        /**
         * @description 默认的节点标题信息，只做显示，当前节点信息中的title是空的
         */
        const _nodeTitle_ = computed(() => {
            if (unref(currentStatusType) === 'code') {
                return '代码规则'
            }
            if (unref(currentStatusType) === 'message') {
                return '消息通知'
            }
            if (unref(currentStatusType) === NodeTypeEnum.START_NODE) {
                return '从哪里开始'
            }
            if (unref(currentStatusType) === NodeTypeEnum.NODE) {
                return '执行动作'
            }
            if (unref(currentStatusType) === NodeTypeEnum.CONDITION_NODE) {
                return '条件'
            }
        })

        const showNodeTitle = computed(() => {
            if (unref(currentStatusType) === 'code') {
                return nodeData.value.options?.fieldOptions?.title || ''
            }
            return nodeData.value.name || ''
        })

        /**
         * @description 删除节点处理函数，可以搜索该事件总线名称，找到触发该事件的地方
         */
        const closeNode = (mode: deleteMode) => {
            currentCtx.$eventBus.$emit('trigger-design-deleteNodeChange', nodeData.value, mode)
        }

        /**
         * @description 点击输入框事件处理函数
         * @param e Event
         */
        const handleInput = (e) => {
            if (unref(currentStatusType) === 'code') {

                // 检查 nodeData.value.options.fieldOptions 是否存在
                if (!nodeData.value.options.fieldOptions) {
                    nodeData.value.options.fieldOptions = {};
                }

                // 设置 title 属性
                currentCtx.$set(nodeData.value.options.fieldOptions, 'title', e)
                

                return;
            }

            // 更新 state 和 nodeName
            state.currentNodeInfoFront.name = e;
            nodeName.value = e;
        }
        /**
         * @description 点击输入框失焦事件
         */
        const handleInputBlur = () => {
            currentCtx.$eventBus.$emit('trigger-design-updateNodeChange', state.currentNodeInfoFront?.uniqueId, state.currentNodeInfoFront)
            setIsEdit(false)
        }

        /**
         * @description 聚焦事件
         * @param e Event
         */
        const handleInputFocus = (e) => {
            e.stopPropagation()
        }

        /**
         * @description 点击normalnode事件处理函数
         * @param e Event
         */
        const clickAppHandler = (e: MouseEvent) => {
            e.stopPropagation()
            if ((e.target as HTMLElement).closest('.process-close')) return;
            if ((e.target as HTMLElement).closest('.process-input-text')) return;

            currentCtx.$eventBus.$emit('trigger-design-node-click', nodeData.value.uniqueId, nodeData.value, state.currentNodeInfoFront)

            state.currentNodeInfoFront = nodeData.value
            state.currentSelectNode = nodeData.value.uniqueId



            if (unref(currentStatusType) === NodeTypeEnum.START_NODE) {
                showOpenPanel(true)
                showAppPage(1)
            }
            if (unref(currentStatusType) === NodeTypeEnum.CONDITION_NODE) {
                showOpenPanel(true)
                showAppPage(2)
            }
            if (unref(currentStatusType) === NodeTypeEnum.NODE) {
                showOpenPanel(true)
                showAppPage(3)
            }
            if (unref(currentStatusType) === 'code') {
                showOpenPanel(true)
                showAppPage(4)
            }
            if (unref(currentStatusType) === 'message') {
                showOpenPanel(true)
                showAppPage(5)
            }
            
        }
        
        /**
         * @description 移除当前节点
         */
        const removeCurrentNodeHandler = () => {

            if (nodeData.value.children.length === 0 || parentConditionDeleteFlag.value) {
                closeNode('current')
                return
            }
            // 如果当前类型不是执行动作节点，则直接关闭
            if (unref(currentStatusType) !== NodeTypeEnum.NODE) {
                closeNode('current')
                return
            }
            currentCtx.$confirm('确定要删除吗？移除后关联数据会被重置清空。', '提示', {
                showCancelButton: true,
                confirmButtonText: "确定移除",
                cancelButtonText: "取消",
                customClass: 'trigger-confirm',
                cancelButtonClass: 'trigger-cancel-button',
                confirmButtonClass: 'trigger-confirm-button',
            })
            .then(() => {
                closeNode('current')
            }).catch((err) => {
                console.error(err)
            })
        }

        /**
         * @description 移除当前节点一下所有节点
         */
        const removeCurrentAllNodeHandler = () => {
            currentCtx.$confirm('确定要移除以下所有节点吗？', '提示', {
                showCancelButton: true,
                confirmButtonText: "确定移除",
                cancelButtonText: "取消",
                customClass: 'trigger-confirm',
                cancelButtonClass: 'trigger-cancel-button',
                confirmButtonClass: 'trigger-confirm-button',
            })
            .then(() => {
                closeNode('all')
            }).catch((err) => {
                console.error(err)
            })
        }

        const removeHandler = () => {
            if (showDeleteCurrent.value) {
                removeCurrentNodeHandler()
            } else if (showDeleteAll.value){
                removeCurrentAllNodeHandler()
            }
        }

        // 显示右边抽屉逻辑
        const showOpenPanel = (item: boolean) => {
            state.data.changeOpenPanel = item
        }
        // 显示应用页面
        const showAppPage = (item: 1 | 2 | 3 | 4 | 5) => {
            state.data.kind = item
        }
        watch(() => state.currentNodeInfoFront, (newValue) => {
            if (Object.keys(newValue).length === 0) return
            // console.log(Object.keys(newValue))
            // console.log(newValue)
            if (!hasUpdateEmit.value) {
                currentCtx.$eventBus.$emit('trigger-design-updateNodeChange', newValue?.uniqueId, newValue)
                hasUpdateEmit.value = true
            }
        }, { deep: true})

        // 侦听编辑状态，如果是编辑状态聚焦输入框
        watch(() => isEdit.value, (newValue) =>{
            if (newValue) {
                nextTick(() => {
                    inputRef.value.focus()
                })
            }
        })

        onMounted(() => {
            nextTick(() => {
                // 新建&编辑页面进入之后点击这个事件
                if (unref(currentStatusType) === NodeTypeEnum.START_NODE) {
                    boxRef.value?.click()
                }
            })
        })

        onBeforeUnmount(() => {
        })

        return ()=> (
            <div class="process-node-normal__container">
                <div class="process-node-normal__box">
                    <div class={`${selectNodeClass.value ? 'process-node-normal__box-wrap active' : 'process-node-normal__box-wrap'} ${validateClass.value ? '' : 'error'} `} onClick={(e) => clickAppHandler(e)} ref={el => boxRef.value = el}>
                        <div class="process-node-normal__box-top">
                            <div class="top_content">
                                <div class="process-input-id">{props.nodeIndex}.</div>
                                <div class="process-input-icon">
                                    {
                                        unref(currentStatusType) ? (
                                            unref(currentStatusType) === 'code' ? (
                                                <span class="iconfont icon-fdn-jsCodeBlock"></span>
                                            ) : nodeData.value.options.type === 'message' ? (
                                                <span class="iconfont icon-apartment"></span>
                                            ) : null
                                        ) : (
                                            [NodeTypeEnum.NODE, NodeTypeEnum.START_NODE].includes(unref(currentStatusType)) ? (
                                                <span class={'iconfont icon-fd-link'}></span>
                                            ) : unref(currentStatusType) === NodeTypeEnum.CONDITION_NODE ? (
                                                 <span class={'iconfont icon-apartment'}></span>
                                            ) : null
                                        )
                                    }
                                </div>
                                <div class="process-input-text">
                                    {
                                        isEdit.value ? (
                                            <el-input value={showNodeTitle.value} onFocus={handleInputFocus} onInput={handleInput} onBlur={handleInputBlur} maxlength={20} ref={el => inputRef.value = el}></el-input>
                                        ) : (
                                            <div onClick={(e) => {
                                                setIsEdit(true)
                                            }} class="text-content">
                                                {showNodeTitle.value ? showNodeTitle.value : _nodeTitle_.value}
                                            </div>
                                        )
                                    }
                                    
                                </div>
                            </div>
                            {/* {
                                nodeData.value.type !== NodeTypeEnum.START_NODE ? (
                                    <el-popconfirm title="确定要删除当前节点吗？" onConfirm={() => closeNode('all')}>
                                        <div class="process-close iconfont icon-close" slot="reference"></div>
                                    </el-popconfirm>
                                ) : null
                            } */}
                            {
                                nodeData.value.type !== NodeTypeEnum.START_NODE ? (
                                    showSelect.value ?(
                                    <el-dropdown placement={'bottom'}>
                                        <div class="process-close iconfont icon-close"></div>
                                        <el-dropdown-menu slot="dropdown">
                                        { showDeleteCurrent.value ? <el-dropdown-item nativeOnClick={removeCurrentNodeHandler}>移除当前节点</el-dropdown-item> : null }
                                        { showDeleteAll.value ?  <el-dropdown-item nativeOnClick={removeCurrentAllNodeHandler}>移除当前及其以下所有节点</el-dropdown-item> : null}
                                        </el-dropdown-menu>
                                    </el-dropdown>
                                    ) : (
                                        <div class="process-close iconfont icon-close" onClick={removeHandler}></div>
                                    )
                                    
                                ) : null
                            }
                            
                        </div>
                        <div class="process-node-normal__box-content">
                            
                            {
                                actionStatus.value ? (
                                    <NodeTriggerContent nodeData={nodeData.value} currentNodeType={currentStatusType.value}/>
                                ) :
                                (
                                    <NodeExecuteContent nodeData={nodeData.value} currentNodeType={currentStatusType.value}/>
                                )
                            }
                            
                            
                        </div>
                    </div>
                    <ArrowLine></ArrowLine>
                    <AddOperatorNode nodeData={nodeData.value} key={nodeData.value.uniqueId}></AddOperatorNode>
                </div>
    
                <div class="process-node-normal__children">
                    {
                        nodeData.value.children.map(nodeItem => {
                            return (
                                    <MainNodeProcessWrap 
                                        key={nodeData.value.uniqueId}
                                        nodeIndex={cNodeIndex.value}
                                        nodeList={nodeItem.children}
                                        nodeData={nodeItem}/>
                            )
                        })
                    }
                </div>
             
            </div>
        )
    }
})